﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using Simulator;
using Statistics;
using ELW.Library.Math;
using ELW.Library.Math.Exceptions;
using ELW.Library.Math.Expressions;
using ELW.Library.Math.Tools;

namespace ModelConfigurator
{
    public partial class FormAction : FormBase
    {
        /// <summary>
        /// блок действия, который редактируется
        /// </summary>
        public Action Edited { get; set; }
        /// <summary>
        /// список загруженных из БД блоков
        /// </summary>
        public List<ActionData> ActionsFromDB { get; set; }
        /// <summary>
        /// Список названий параметров ресурсов
        /// </summary>
        public List<string> ParamNames { get; set; }
        
        public FormAction()
        {
            InitializeComponent();
        }

        private void FormAction_Load(object sender, EventArgs e)
        {
            ImageList lst = new ImageList();

            lst.Images.Add(ModelConfigurator.Properties.Resources.small_database);//загрузим картинку "база данных"
            lst.Images.Add(ModelConfigurator.Properties.Resources.small_resources);//загрузим картинку для действий

            treeViewActions.ImageList = lst;

            //добавим узлы в базу данных
            TreeNode[] tr = new TreeNode[ActionsFromDB.Count];
            TreeNode db;
            for(int i=0; i < ActionsFromDB.Count; i++)
            {
                tr[i] = new TreeNode(ActionsFromDB[i].Name, 1, 1);
                tr[i].Name = "ActionNode" + i;
            }
            db = new TreeNode("База данных", 0, 0, tr);
            db.Name = "DatabaseNode";
            treeViewActions.Nodes.Add(db);

            FillActionData(Edited as IActionData);

            //заполним таблицу весов ресурсов

            for (int i = 0; i < Edited.Resources.Count; i++)
            {
               dataGridViewRes.Columns.Add("ColumnRes" + i,Edited.Resources[i].Text);
               //заполним комбо-бокс ресурсов
               comboBoxRes.Items.Add(Edited.Resources[i].Text);
            }
            //если есть 1 и более ресурсов
            if (Edited.Resources.Count > 0)
            {
                //добавим строку и заполним ее весами
                dataGridViewRes.Rows.Add();
                for (int i = 0; i < Edited.Resources.Count; i++)
                {
                    dataGridViewRes[i, 0].Value = Edited.WeightsR[i];
                }
            }
            //укажем ресурс в комбо-боксе
            if (Edited.Resources.Count > 0)
            {
                comboBoxRes.SelectedItem = comboBoxRes.Items[0];
            }
            //заполним таблицу весов параметров: сначала добавим столбцы
            for (int i = 0; i < ParamNames.Count; i++)
            {
                dataGridViewParams.Columns.Add("ColumnParams" + i, ParamNames[i]);
                if (ParamNames[i] == "")
                {
                    dataGridViewParams.Columns["ColumnParams" + i].Visible = false;
                }
                //заполним комбо-бокс параметров
                else
                    comboBoxParam.Items.Add(ParamNames[i]);
            }
            if (ParamNames.Count > 0)
            {
                dataGridViewParams.Rows.Add();
            }
            //заполним столбцы
            for (int i = 0; i < ParamNames.Count; i++)
            {
                dataGridViewParams[i, 0].Value = Edited.WeightsP[i];
                
            }
            //укажем параметр в комбо-боксе
            if (ParamNames.Count > 0)
            {
                comboBoxParam.SelectedItem = comboBoxParam.Items[0];
            }
            textBoxName.Text = Edited.Text;
            RedrawLabelP();

            //настроим единицы измерения времени
            switch (Edited.SimulationTimeUnits)
            {
                case TimeUnits.days:
                    comboBoxTime.SelectedItem = comboBoxTime.Items[0];
                    break;
                case TimeUnits.hours:
                    comboBoxTime.SelectedItem = comboBoxTime.Items[1];
                    break;
                case TimeUnits.minutes:
                    comboBoxTime.SelectedItem = comboBoxTime.Items[2];
                    break;
                default:
                    comboBoxTime.SelectedItem = comboBoxTime.Items[3];
                    break;
            }

            try
            {
                textBoxTime.Text = String.Format("{0}", ToolsHelper.Decompiler.Decompile(Edited.TimeCompiledString));
            }catch
            {
                errorProvider1.SetError(textBoxTime,"Неверное выражение");
            }
            try
            {
                textBoxQuality.Text = String.Format("{0}", ToolsHelper.Decompiler.Decompile(Edited.QualityCompiledString));
            }
            catch
            {
                errorProvider1.SetError(textBoxQuality, "Неверное выражение");
            }
        }

        private void FillActionData(IActionData a)
        {
            textBoxTime.Text = a.TimeString;
            textBoxQuality.Text = a.QualityString;
        }
        /// <summary>
        /// Изменить текст на метке в соответствии со значение обобщенного параметра ресурсов
        /// </summary>
        private void RedrawLabelP()
        {
            labelP.Text = "Обобщенный параметр ресурсов Р = " + Edited.CalcParam().ToString("N2",
                System.Globalization.CultureInfo.CreateSpecificCulture("ru-RU"));
        }

        private void comboBoxQ_SelectedIndexChanged(object sender, EventArgs e)
        {
            //добавить код
        }

        private void dataGridViewCoefs_CellContentClick(object sender, DataGridViewCellEventArgs e)
        {

        }

        private void comboBoxT_SelectedIndexChanged(object sender, EventArgs e)
        {
            //добавить код
        }
        /// <summary>
        /// Проверка, является ли текст числом типа Double. Если нет, выз. ErrorProvider
        /// </summary>
        /// <param name="s">Текстовая строка</param>
        /// <param name="ctr">Элемент управления, которому присвоится ErrorProvider</param>
        /// <returns>ИСТИНА если является double, иначе ЛОЖЬ</returns>
        private bool CheckDouble(string s, Control ctr)
        {
            bool b = true;
            errorProvider1.Clear();
            try
            {
                Convert.ToDouble(s);
            }
            catch
            {
                b = false;
                errorProvider1.SetError(ctr, "В ячейку можно ввести только число типа double");
            }
            return b;
        }


        private void dataGridViewRes_CellContentClick(object sender, DataGridViewCellEventArgs e)
        {
            
        }

        private void dataGridViewParams_CellContentClick(object sender, DataGridViewCellEventArgs e)
        {
            
        }

        private void checkBoxRes_CheckedChanged(object sender, EventArgs e)
        {
            //модиф. доступность комбо-бокса и таблицы
            dataGridViewRes.Enabled = !(sender as CheckBox).Checked;
            comboBoxRes.Enabled = (sender as CheckBox).Checked;
            //пересчитаем теперь веса в Edited
            int ind = comboBoxRes.SelectedIndex;
            for (int i = 0; i < Edited.Resources.Count; i++)
            {//пройдемся ресурсам
                //если поставили флажок
                if ((sender as CheckBox).Checked)
                {
                    if (i == ind)//изменим все веса
                        Edited.WeightsR[i] = 1;
                    else
                        Edited.WeightsR[i] = 0;
                }
                else
                {//если сняли флажок - запишем всю табицу
                    Edited.WeightsR[i] = Convert.ToDouble(dataGridViewRes[i, 0].Value);
                }
            }
            RedrawLabelP();
        }

        private void checkBoxParam_CheckedChanged(object sender, EventArgs e)
        {
            //модиф. доступность комбо-бокса и таблицы
            dataGridViewParams.Enabled = !(sender as CheckBox).Checked;
            comboBoxParam.Enabled = (sender as CheckBox).Checked;

            //пересчитаем теперь веса в Edited
            int ind = comboBoxParam.SelectedIndex;
            for (int i = 0; i < ParamNames.Count; i++)
            {//пройдемся ресурсам
                //если поставили флажок
                if ((sender as CheckBox).Checked)
                {
                    if (i == ind)//изменим все веса
                        Edited.WeightsP[i] = 1;
                    else
                        Edited.WeightsP[i] = 0;
                }
                else
                {//если сняли флажок - запишем всю табицу
                    Edited.WeightsP[i] = Convert.ToDouble(dataGridViewParams[i, 0].Value);
                }
            }
            RedrawLabelP();
        }

        private void treeViewActions_AfterSelect(object sender, TreeViewEventArgs e)
        {
            TreeNode tn = treeViewActions.SelectedNode;
            ActionData ad;
            if (tn != null)
            {
                if (tn.Name.Contains("Action"))
                {//если выделен узел действия
                    //найдем данные из БД 
                    ad = ActionsFromDB.Find(delegate(ActionData a) { return (a.Name == tn.Text); });
                    //заполним поля, соотв. actionData
                    FillActionData(ad as IActionData);
                    Edited.UpdateByActionData(ad);//обновим Edited
                    textBoxName.Text = ad.Name;
                    //настроим единицы измерения времени
                    switch (ad.SimulationTimeUnits)
                    {
                        case TimeUnits.days:
                            comboBoxTime.SelectedItem = comboBoxTime.Items[0];
                            break;
                        case TimeUnits.hours:
                            comboBoxTime.SelectedItem = comboBoxTime.Items[1];
                            break;
                        case TimeUnits.minutes:
                            comboBoxTime.SelectedItem = comboBoxTime.Items[2];
                            break;
                        default:
                            comboBoxTime.SelectedItem = comboBoxTime.Items[3];
                            break;
                    }
                }
            }
        }

        private void comboBoxRes_SelectedIndexChanged(object sender, EventArgs e)
        {
            int ind = (sender as ComboBox).SelectedIndex;
            for (int i = 0; i < Edited.Resources.Count; i++)
            {//пройдемся ресурсам
                if (i == ind)//изменим все веса
                    Edited.WeightsR[i] = 1;
                else
                    Edited.WeightsR[i] = 0;
            }
            RedrawLabelP();
        }

        private void comboBoxParam_SelectedIndexChanged(object sender, EventArgs e)
        {
            string s = (sender as ComboBox).SelectedItem as string;
            for (int i = 0; i < ParamNames.Count; i++)
            {//пройдемся параметрам
                if (s == ParamNames[i])//изменим все веса
                    Edited.WeightsP[i] = 1;
                else
                    Edited.WeightsP[i] = 0;
            }
            RedrawLabelP();
        }

        private void dataGridViewParams_CellEndEdit(object sender, DataGridViewCellEventArgs e)
        {//проверим, является ли полученное значение типа double
            DataGridViewCell c = (sender as DataGridView)[e.ColumnIndex, e.RowIndex];
            if (CheckDouble((c.Value as string), (sender as DataGridView)))
            {//если double
                Edited.WeightsP[e.ColumnIndex] = Convert.ToDouble(c.Value);
            }
            RedrawLabelP();
        }

        private void dataGridViewRes_CellEndEdit(object sender, DataGridViewCellEventArgs e)
        {
            //проверим, является ли полученное значение типа double
            DataGridViewCell c = (sender as DataGridView)[e.ColumnIndex, e.RowIndex];
            if (CheckDouble((c.Value as string), (sender as DataGridView)))
            {//если double
                Edited.WeightsR[e.ColumnIndex] = Convert.ToDouble(c.Value);
            }
            RedrawLabelP();
        }

        private void textBoxName_TextChanged(object sender, EventArgs e)
        {
            Edited.Text = textBoxName.Text;
        }

        private void buttonOK_Click(object sender, EventArgs e)
        {
            //проверим, верно ли содержание текстовых полей
            if (txtCheck(textBoxQuality) && txtCheck(textBoxTime))
            {
                Edited.TimeString = textBoxTime.Text;
                Edited.QualityString = textBoxQuality.Text;
                this.DialogResult = System.Windows.Forms.DialogResult.OK;
                this.Close();
            }
        }

        private void buttonCancel_Click(object sender, EventArgs e)
        {
            this.DialogResult = System.Windows.Forms.DialogResult.Cancel;
            this.Close();
        }

        private void groupBox2_Enter(object sender, EventArgs e)
        {

        }

        private void labelP_Click(object sender, EventArgs e)
        {

        }

        private void groupBoxHelp_Enter(object sender, EventArgs e)
        {

        }

        private void groupBoxSet_Enter(object sender, EventArgs e)
        {

        }

        private void textBoxDescription_TextChanged(object sender, EventArgs e)
        {

        }

        private void buttonHelp_Click(object sender, EventArgs e)
        {
            string openCHMFile = Application.StartupPath + "\\Справка SAPR-SIM.chm";
            try
            {
                if (!System.IO.File.Exists(openCHMFile))
                    System.IO.File.WriteAllBytes(openCHMFile, global::ModelConfigurator.Properties.Resources.Справка_SAPR_SIM);
            }
            catch
            {
                //если файл есть он не перепишется
            }
            helpProvider1.HelpNamespace = openCHMFile;
            Help.ShowHelp(this, this.helpProvider1.HelpNamespace, HelpNavigator.Topic, "module_2_6_1.htm");
        }

        private void groupBox1_Enter(object sender, EventArgs e)
        {

        }

        private void tabControl1_SelectedIndexChanged(object sender, EventArgs e)
        {

        }

        private void label1_Click(object sender, EventArgs e)
        {

        }

        private void label2_Click(object sender, EventArgs e)
        {

        }

        private void label3_Click(object sender, EventArgs e)
        {

        }

        private void label4_Click(object sender, EventArgs e)
        {

        }

        private void label6_Click(object sender, EventArgs e)
        {

        }

        private void label5_Click(object sender, EventArgs e)
        {

        }

        private void dataGridViewParams_CellContentClick_1(object sender, DataGridViewCellEventArgs e)
        {

        }

        private void dataGridViewRes_CellContentClick_1(object sender, DataGridViewCellEventArgs e)
        {

        }

        private void tabPage1_Click(object sender, EventArgs e)
        {

        }

        private void label7_Click(object sender, EventArgs e)
        {

        }

        private void tabPage2_Click(object sender, EventArgs e)
        {

        }

        private void label8_Click(object sender, EventArgs e)
        {

        }

        private void tabPage3_Click(object sender, EventArgs e)
        {

        }

        private void textBoxQuality_TextChanged(object sender, EventArgs e)
        {

        }

        private void textBoxTime_Leave(object sender, EventArgs e)
        {
            if (txtCheck(textBoxTime))
                Edited.TimeString = textBoxTime.Text; 

        }

        /// <summary>
        /// Проверка содержимого текстового поля на корректность выражения для парсера
        /// </summary>
        /// <param name="txt"></param>
        /// <returns></returns>
        private bool txtCheck(TextBox txt)
        {
            bool b = false;
            errorProvider1.Clear();
            try
            {
                string s = txt.Text;
                //пробуем посчитать
                List<VariableValue> variables = new List<VariableValue>();
                variables.Add(new VariableValue(0, "C"));
                variables.Add(new VariableValue(0, "P"));
                variables.Add(new VariableValue(0, "Q"));

                PreparedExpression preparedExpression = ToolsHelper.Parser.Parse(s);
                CompiledExpression cmp = ToolsHelper.Compiler.Compile(preparedExpression);
                ToolsHelper.Calculator.Calculate(cmp, variables);

                b = true;
            }
            catch (CompilerSyntaxException ex)
            {
                errorProvider1.SetError(txt, String.Format("Ошибка компиляции: {0}", ex.Message));
            }
            catch (MathProcessorException ex)
            {
                errorProvider1.SetError(txt, String.Format("Ошибка: {0}", ex.Message));
            }
            catch (ArgumentException)
            {
                errorProvider1.SetError(txt, "Неверно введенные данные.");
            }
            catch (Exception)
            {
                errorProvider1.SetError(txt, "Непредвиденная ошибка.");
                throw;
            }
            return b;
        }

        private void textBoxQuality_Leave(object sender, EventArgs e)
        {
            if(txtCheck(textBoxQuality))
                Edited.QualityString = textBoxQuality.Text; 

        }

        private void textBoxTime_TextChanged(object sender, EventArgs e)
        {

        }

        private void comboBoxTime_SelectedIndexChanged(object sender, EventArgs e)
        {
            //настроим единицы измерения времени
            switch (comboBoxTime.SelectedIndex)
            {
                case 0:
                    Edited.SimulationTimeUnits = TimeUnits.days;
                    break;
                case 1:
                    Edited.SimulationTimeUnits = TimeUnits.hours;
                    break;
                case 2:
                    Edited.SimulationTimeUnits = TimeUnits.minutes;
                    break;
                default:
                    Edited.SimulationTimeUnits = TimeUnits.seconds;
                    break;
            }
        }

        private void label15_Click(object sender, EventArgs e)
        {

        }
    }
}
